package core.algorithm;

import core.observer.Observer;
import core.problem.FactoryProblems;
import core.problem.Individual;
import core.problem.Population;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author 郝国生 HAO Guo-Sheng
 */
public abstract class AbstractAlgorithm implements Algorithm {

    private Observer observer;//算法观测器

    @Override
    public final void operats(Population population) {
        //final不允许子类对该方法进行修改，这里组装了必要的步骤，属于模板模式
        List<Individual> operatedIndividuals = this.operatePopulation(population);
        //进化过程,不同的算法有不同的方法，会不一样，因此，这个方法要求各个算法自己实现
        
        //把最优个体保留进入当前种群
        try {
            //最优个体放在第0个位置
            operatedIndividuals.add(0, ((Individual) observer.getBestIndividuals()
                    .get(observer.getBestIndividuals().size()-1)).clone());
            //移除最后一个个体
            operatedIndividuals.remove(population.getIndividuals().size() - 1);
        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(AbstractAlgorithm.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (!FactoryProblems.currentProblem.isIECProblem()) {//不是交互式进化计算，则直接获取个体适应值
            for (int i = 0; i < operatedIndividuals.size(); i++) {
                FactoryProblems.currentProblem.evaluate(operatedIndividuals.get(i));
            }
        } else {//是交互式进化计算，则重置其适应值为默认值
            operatedIndividuals.forEach((ind) -> {
                ((Individual) ind).getDecisionVariable().setFitness(new double[]{0});
            });
        }
        population.getIndividuals().clear();
        population.getIndividuals().addAll(operatedIndividuals);
    }

    @Override
    public void onceGetFitness4TEC(Population population) {
        //只有非交互式进化计算才需要计算适应值
        //这个方法在一次实验中只会被调用1次，即只针对初始种群
        population.getIndividuals().forEach((ind) -> {
            FactoryProblems.currentProblem.evaluate((Individual) ind);
        });
    }

    @Override
    public void init() {
        observer = new Observer();
    }
    //记录最优个体变化情况

    @Override
    public String getName() {
        return "Abstract algorithm";
    }

    private void outputSolution(List<Individual> individuals) {
        for (Individual ind : individuals) {
            switch (ind.getDecisionVariable().getGenecodeType()) {
                case DOUBLECODE:
                case AFFINEFACECODE:
                case NORMALFACECODE:
                    System.out.printf("%6.4f;", ind.getDecisionVariable().getGeneCodes()[0]);
                    break;
                case STRINGCODE:
                    System.out.printf(ind.getDecisionVariable().getGenecodesString());
                    break;
                case BINARYCODE:
                    System.out.printf(ind.getDecisionVariable().getGenecodesString());
                    break;
            }

        }
        System.out.println("");
    }
    //当需要可视化时，通过ready值调整控制进化步调，当ready=true时，继续进化，否则等待
    boolean ready = true;

    @Override
    public Observer getObserver() {
        return observer;
    }

}
